package com.xsd.juc;

/**
 * @Description: 线程池
 * @Author: zhoufuzong
 * @Created: 2021-01-02 21:57:09
 * @Version: 1.1.0
 */

import java.util.concurrent.*;

/**
 * 线程池的优势：
 * 线程池做的工作只要是控制运行的线程数量，处理过程中将任务放入队列，然后在线程创建后启动这些任务，如果线程数量超过了
 * 最大的数量，超出数量的线程排队等候，等其他线程执行完毕，再从队列中取出任务来执行
 *
 *
 * 它的主要特点为：线程复用；控制最大并发数；管理线程。
 *
 * 第一：降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的资源消耗/
 * 第二：提高响应速度。当任务到达时，任务可以不需要等待线程就能立即执行。
 * 第三：提高线程的客观理性。线程是稀缺资源，如果无限制的创建，不仅会消耗系统资源，
 * 还会降低系统的稳定性，使用线程池可以进行统一的分配，调优和监控
 */
public class ThreadPoolDemo {
    public static void main(String[] args) {

        /**
         * cpu 密集型计算：非常占cpu 的 ，cpu 最大核数+1~2， = max
         *
         * IO 密集型计算：
         */

        // 内核数
        System.out.println(Runtime.getRuntime().availableProcessors());
        ExecutorService threadPool = new ThreadPoolExecutor(
                2,
                5,
                2L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(3),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        /*
           AbortPolicy (): 默认：直接抛出RejectedExcutionException异常阻止系统正常运行
            CallerRunsPolicy ： 假如是main 调用的，那么就把任务回退给main去调用
            DiscardPolicy(): 接收不了的，就抛弃掉
           DiscardOldestPolicy(): 抛弃队列中等待最久的任务，然后把当前任务加入队列中尝试再次提交当前任务。


         */

        try {
            for (int i = 1; i <=6 ; i++) {
//                try{ TimeUnit.MILLISECONDS.sleep(100); } catch(InterruptedException e) {e.printStackTrace();}

                threadPool.execute(()->{
                    System.out.println(Thread.currentThread().getName()+"\t 办理业务");
                });

            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            threadPool.shutdown();
        }
    }

    private static void threadPoolDemo() {
        // 一池五个受理线程，类似一个银行有5个受理窗口
//        ExecutorService threadPool  = Executors.newFixedThreadPool(5);

        // 一池 一个工作线程，类似一个银行有一个受理窗口
//        ExecutorService threadPool = Executors.newSingleThreadExecutor();

        // 执行很多短期异步任务，线程池根据需要创建新线程，但在先前构建的线程可用时将重用它们，可扩容，遇强则强
        //  一池N 个线程
        ExecutorService threadPool = Executors.newCachedThreadPool();

        try {
            for (int i = 1; i <=10 ; i++) {
                try{ TimeUnit.SECONDS.sleep(2); } catch(InterruptedException e) {e.printStackTrace();}

                threadPool.execute(()->{
                     System.out.println(Thread.currentThread().getName()+"\t 办理业务");
                });

            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            threadPool.shutdown();
        }
    }
}
